package pe.com.bbva.efcap.servidor.servicio.impl;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

import org.boris.expr.ExprException;
import org.boris.expr.engine.DependencyEngine;
import org.boris.expr.engine.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pe.com.bbva.efcap.servidor.bean.rating.RatingBean;
import pe.com.bbva.efcap.servidor.bean.rating.RatingPeriodoBean;
import pe.com.bbva.efcap.servidor.dao.DetalleSimulacionDAO;
import pe.com.bbva.efcap.servidor.dao.IndicadorDAO;
import pe.com.bbva.efcap.servidor.modelo.entidad.DetalleSimulacion;
import pe.com.bbva.efcap.servidor.modelo.entidad.Indicador;
import pe.com.bbva.efcap.servidor.modelo.entidad.Simulacion;
import pe.com.bbva.efcap.servidor.servicio.MotorFormulasService;
import pe.com.bbva.efcap.servidor.util.Constante;

@Service
@Transactional(readOnly=true)
public class MotorFormulasServiceImpl implements MotorFormulasService{

	@Autowired
	private IndicadorDAO indicadorDAO;
	
	@Autowired
	private DetalleSimulacionDAO detalleSimulacionDAO;
		
	@Override
	public DependencyEngine calcularFormulasRating(DependencyEngine engine, RatingBean ratingBean, String catalogo){
		List<Indicador> indicadores = indicadorDAO.obtenerListaIndicadoresPorCatalogo(catalogo);
		System.out.println("CATALOGO: "+catalogo);
		try {
			for(Indicador i : indicadores){
				if(i.getTipoTipo().getNombreCorto().equals(Constante.TIPO_INDICADOR_NUMERICO)
						&& !i.getCodigoCuenta().trim().equals(Constante.CUENTA_0)){
					int j = 0;
					System.out.print(i.getCodigoCuenta()+"\t");
					for(RatingPeriodoBean p : ratingBean.getPeriodos()){
						Double monto = p.getMontoPorCuenta(i.getCodigoCuenta().trim());
						String variable = Constante.ABC[j]+Constante.CUENTAS+i.getCodigo();
						String formula = String.format(Locale.US,"%1.2f",monto);
						engine.set(variable, "="+formula);
						System.out.print(variable+"="+formula+"\t");
						j++;
					}
					System.out.println();
				}
			}
			for(Indicador i : indicadores){
				if(i.getTipoTipo().getNombreCorto().equals(Constante.TIPO_INDICADOR_NUMERICO)){
					System.out.print(i.getCodigoCuenta()+"\t");
					for(int k=0; k<ratingBean.getPeriodos().size(); k++){
						String variable = Constante.ABC[k]+catalogo+i.getCodigo();
						String formula = anidarColumnaACatalogoEnFormula(Constante.ABC[k], Constante.CUENTAS,
								anidarColumnaACatalogoEnFormula(Constante.ABC[k], Constante.BALANCE_GENERAL,
								anidarColumnaACatalogoEnFormula(Constante.ABC[k], Constante.RATIOS,
								anidarColumnaACatalogoEnFormula(Constante.ABC[k], Constante.ESTADO_PERDIDAS_GANANCIAS,
								anidarColumnaACatalogoEnFormula(Constante.ABC[k], Constante.DATOS_ADICIONALES,
								anidarColumnaACatalogoEnFormula(Constante.ABC[k], Constante.DEUDA_INDIRECTA,
										i.getFormula0()))))));
						System.out.print(" "+variable+"="+formula+"\t");
						engine.set(variable, "="+formula);
					}
					System.out.println();
				}
			}
			return engine;
		} catch (ExprException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		return null;
	}

	@Override
	@Transactional(readOnly=false)
	public void registrarDetalleSimulacionRating(Simulacion simulacion, DependencyEngine e, RatingBean rating, String catalogo) throws NumberFormatException, ExprException{
		List<Indicador> indicadores = indicadorDAO.obtenerListaIndicadoresPorCatalogo(catalogo);
		Calendar calendar = Calendar.getInstance();
		Timestamp timestamp = new Timestamp(calendar.getTimeInMillis());
		for(Indicador i : indicadores){
			if(i.getTipoTipo().getNombreCorto().equals(Constante.TIPO_INDICADOR_NUMERICO)){
				for(int k=0; k<rating.getPeriodos().size(); k++){
					Double monto = Double.parseDouble(
								e.getValue(Range.valueOf(
										Constante.ABC[k]+
										catalogo+
										i.getCodigo())).toString());
					DetalleSimulacion detalleSimulacion = new DetalleSimulacion();
					detalleSimulacion.setPeriodo(rating.getPeriodos().get(k).getPeriodo());
					detalleSimulacion.setRecalcular(new BigDecimal(0));
					detalleSimulacion.setSimulacion(simulacion);
					detalleSimulacion.setTipoDependencia(new BigDecimal(Constante.TIPO_DEPENDENCIA_FORMULA_0));
					detalleSimulacion.setIndicador(i);
					detalleSimulacion.setValor(String.format(Locale.US,"%1.2f",monto));
					detalleSimulacion.setFechaCreacion(timestamp);
					detalleSimulacion.setFechaActualizacion(detalleSimulacion.getFechaCreacion());
					detalleSimulacionDAO.guardar(detalleSimulacion);
				}
			}
		}
		
	}
	
	private String anidarColumnaACatalogoEnFormula(String columna, String catalogo, String formula){
		int pcat = 0; //indica de posicion para la cadena catalogo		
		String cadena = "";
		String cadDer = formula;
		pcat = cadDer.indexOf(catalogo);
		while (pcat != -1){
			String cadIzq = cadDer.substring(0, pcat + catalogo.length());
			cadDer = cadDer.substring(pcat + catalogo.length());
			if((cadIzq.length() == catalogo.length() 
					|| !Character.isLetter(cadIzq.charAt(cadIzq.length()-catalogo.length()-1)) ) 
					&& (cadDer.length() > 0 && Character.isDigit(cadDer.charAt(0)))){
				cadIzq = cadIzq.replace(catalogo, columna+catalogo);
			}
			cadena+=cadIzq;
			pcat = cadDer.indexOf(catalogo);
		}
		cadena+=cadDer;
		return cadena;
	}
	
}
